﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Nanohope_v1._0
{
    public class Character
    {
        #region Constants

        private const float SPEED = 250f;
        private const float JUMP_POWER = 200f;
        private const float GRAVITY = 5f;
        private const float FRICTION = 50f;
        private const int DASH_DISTANCE = 150;

        #endregion

        #region Attributes

        public enum CharState
        {
            OnGround,
            Jumping,
            DoubleJumping,
            OnWall
        }

        private Animation animation;

        private KeyboardState KeyState
        {
            get;
            set;
        }

        private CharState State
        {
            get;
            set;
        }

        private Texture2D Texture
        {
            get;
            set;
        }

        private Rectangle Area
        {
            get;
            set;
        }

        private Vector2 Position
        {
            get;
            set;
        }

        private Vector2 Velocity
        {
            get;
            set;
        }

        private Vector2 OldPosition
        {
            get;
            set;
        }

        private Vector2 JumpPosition
        {
            get;
            set;
        }

        private double DashTimer
        {
            get;
            set;
        }

        private bool RightPressed
        {
            get;
            set;
        }

        private bool LeftPressed
        {
            get;
            set;
        }

        private bool DashPressed
        {
            get;
            set;
        }

        private bool FacingRight
        {
            get;
            set;
        }

        private bool Dashing
        {
            get;
            set;
        }

        private bool OnAirDashing
        {
            get;
            set;
        }

        #endregion

        #region Methods

        public Character()
        {
            Velocity = Vector2.Zero;
            Position = new Vector2(300, 350);
            State = CharState.DoubleJumping;
            Texture = Game1.walking;
            FacingRight = true;
            DashPressed = false;
            animation = new Animation(14, 56, Texture.Height, Texture);
        }

        public void Update(GameTime gameTime)
        {
            //Checa se botão tá pressionado
            KeyState = Keyboard.GetState();
            if (KeyState.IsKeyDown(Keys.I))
            {
                CanvasManager.instance.backToMenuInGame();
            }

            if (KeyState.IsKeyDown(Keys.Left))
            {
                LeftPressed = true;
                if (Dashing && FacingRight)
                {
                    StopDash();
                }
            }
            else
            {
                LeftPressed = false;
            }
            if (KeyState.IsKeyDown(Keys.Right))
            {
                RightPressed = true;
                if (Dashing && !FacingRight)
                {
                    StopDash();
                }
            }
            else
            {
                RightPressed = false;
            }
            if (KeyState.IsKeyDown(Keys.D) && DashPressed)
            {
                DashPressed = true;
            }
            else
            {
                DashPressed = false;
            }

            //Atualiza direção
            if (Velocity.X > 0)
            {
                animation.Update(gameTime);
                FacingRight = true;
            }
            else if(Velocity.X < 0)
            {
                animation.Update(gameTime);
                FacingRight = false;
            }

            Console.WriteLine(State);

            //Atualiza área de colisão
            Rectangle area = new Rectangle((int)Position.X, (int)Position.Y, Texture.Width, Texture.Height);
            Area = area;

            //Checa ações
            switch (State)
            {
                case CharState.OnGround:
                    OnGround();
                    break;
                case CharState.OnWall:
                    OnWall();
                    break;
                case CharState.Jumping:
                    Jumping();
                    break;
                case CharState.DoubleJumping:
                    DoubleJumping();
                    break;
            }

            //Dash
            if (Dashing)
            {
                Dash(gameTime);
                if (!DashPressed)
                {
                    StopDash();
                }
            }
            if (OnAirDashing)
            {
                StopDash();
            }
            //Atualiza posição
            Position += Vector2.Multiply(Velocity, (float)gameTime.ElapsedGameTime.TotalSeconds);
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            animation.onDraw(spriteBatch, Position, FacingRight);
            /*if (FacingRight)
            {
                spriteBatch.Draw(Texture, Position, Color.White);
            }
            else
            {
                spriteBatch.Draw(Texture, Position, null, Color.White, 0f, Vector2.Zero, 1f, SpriteEffects.FlipHorizontally, 0);
            }*/
        }

        private void DoubleJumping()
        {
            //Checa comandos
            if (KeyState.IsKeyDown(Keys.Right))
            {
                if (Velocity.X < SPEED)
                {
                    Velocity += new Vector2(5, 0);
                }
            }
            if (KeyState.IsKeyDown(Keys.Left))
            {
                if (Velocity.X > -SPEED)
                {
                    Velocity -= new Vector2(5, 0);
                }
            }

            //Funções de física
            ApplyGravity();
        }

        private void Jumping()
        {
            //Checa comandos
            if (KeyState.IsKeyDown(Keys.Up) && Position.Y < JumpPosition.Y - 50)
            {
                State = CharState.DoubleJumping;
                Velocity = new Vector2(Velocity.X, 0);
                Velocity -= new Vector2(0, JUMP_POWER);
            }
            if (KeyState.IsKeyDown(Keys.Right))
            {
                if (Velocity.X < SPEED)
                {
                    Velocity += new Vector2(10, 0);
                }
            }
            if (KeyState.IsKeyDown(Keys.Left))
            {
                if (Velocity.X > -SPEED)
                {
                    Velocity -= new Vector2(10, 0);
                }
            }
            if (KeyState.IsKeyDown(Keys.D) && !Dashing
                && !DashPressed)
            {
                DashPressed = true;
                Dashing = true;
                OldPosition = Position;
            }

            //Funções de física
            ApplyGravity();
        }

        private void OnWall()
        {
            //Checa estado
            if ((!LeftPressed && !FacingRight) || (!RightPressed && FacingRight))
            {
                State = CharState.DoubleJumping;
                return;
            }

            //Checa comandos
            if (KeyState.IsKeyDown(Keys.Up))
            {
                State = CharState.Jumping;
                if (RightPressed && FacingRight)
                {
                    Velocity = Vector2.Add(Velocity, new Vector2(-SPEED, -JUMP_POWER));
                }
                if (LeftPressed && !FacingRight)
                {
                    Velocity = Vector2.Add(Velocity, new Vector2(SPEED, -JUMP_POWER));
                }
            }
        }

        private void OnGround()
        {
            //Checa comandos
            if (KeyState.IsKeyDown(Keys.Right))
            {
                Velocity = new Vector2(SPEED, 0);
            }
            else
            {
                if (KeyState.IsKeyDown(Keys.Left))
                {
                    Velocity = new Vector2(-SPEED, 0);
                }
                else
                {
                    Velocity = Vector2.Zero;
                }
            }
            if (KeyState.IsKeyDown(Keys.Up))
            {
                State = CharState.Jumping;
                JumpPosition = Position;
                Velocity -= new Vector2(0, JUMP_POWER);
            }
            if (KeyState.IsKeyDown(Keys.D) && !Dashing
                && !DashPressed)
            {
                DashPressed = true;
                Dashing = true;
                OldPosition = Position;
            }
        }

        public void CheckCollision(List<Objects> objects)
        {
            Vector2 pos;

            for (int i = 0; i < objects.Count; i++)
            {
                if (objects[i] is Wall)
                {
                    if (State != CharState.OnWall && Area.Intersects(objects[i].Area))
                    {
                        StopDash();
                        if (FacingRight)
                        {
                            pos = new Vector2(objects[i].Position.X - Texture.Width - 1, Position.Y);
                        }
                        else
                        {
                            pos = new Vector2(objects[i].Area.Width + 1, Position.Y);
                        }
                        Position = pos;

                        if ((State == CharState.Jumping || State == CharState.DoubleJumping) && (LeftPressed || RightPressed))
                        {
                            State = CharState.OnWall;
                            Velocity = new Vector2(0, FRICTION);
                        }
                        else
                        {
                            Velocity = Vector2.Zero;
                        }
                    }
                }
                else
                {
                    if (objects[i] is Ground && State != CharState.OnGround && Area.Intersects(objects[i].Area))
                    {
                        pos = new Vector2(Position.X, objects[i].Position.Y - Texture.Height - 1);
                        Position = pos;
                        Velocity = Vector2.Zero;
                        State = CharState.OnGround;
                    }
                }
            }
        }

        private void ApplyGravity()
        {
            Velocity += new Vector2(0, GRAVITY);
        }

        private void Dash(GameTime gameTime)
        {
            DashTimer = gameTime.TotalGameTime.TotalSeconds;
            if (FacingRight)
            {
                Velocity = new Vector2(SPEED * 2, Velocity.Y);
            }
            else
            {
                Velocity = new Vector2(-SPEED * 2, Velocity.Y);
            }

            if (Position.X < OldPosition.X - 150 || Position.X > OldPosition.X + 150)
            {
                StopDash();
            }
        }

        private void StopDash()
        {
            Dashing = false;
            if (State == CharState.OnGround)
            {
                Velocity = new Vector2(Velocity.X / 3, Velocity.Y);
                OnAirDashing = false;
            }
            else
            {
                OnAirDashing = true;
            }
        }

        #endregion
    }
}